package cn.iocoder.yudao.module.wms.service.rdrecord10;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.wms.controller.admin.productionorder.vo.ProductionOrderSaveReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.productionorder.vo.ProductionOrdersRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord10.vo.Rdrecord10PageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord10.vo.Rdrecord10SaveReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord10.vo.Rdrecords10RespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.productionorder.ProductionOrderDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord10.Rdrecord10DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord10.Rdrecords10DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord10.Rdrecord10Mapper;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord10.Rdrecords10Mapper;
import cn.iocoder.yudao.module.wms.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.wms.dal.redis.serialNumber.WmsSerialNumberRedisDAO;
import cn.iocoder.yudao.module.wms.service.batch.BatchService;
import cn.iocoder.yudao.module.wms.service.productionorder.ProductionOrderService;
import cn.iocoder.yudao.module.wms.service.stock.StockService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.*;

/**
 * 生产入库主 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class Rdrecord10ServiceImpl implements Rdrecord10Service {
    public static final String PROCESS_KEY = "rdrecord10";
    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private Rdrecord10Mapper rdrecord10Mapper;
    @Resource
    private Rdrecords10Mapper rdrecords10Mapper;
    @Resource
    private WmsSerialNumberRedisDAO serialNumberRedisDAO;
    @Resource
    private ProductionOrderService productionOrderService;
    @Resource
    private StockService stockService;
    @Resource
    private BatchService batchService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createRdrecord10(Rdrecord10SaveReqVO createReqVO) {
        // 插入
        String serialNumber = serialNumberRedisDAO.generate(WmsSerialNumberRedisDAO.POMAIN_SERIAL_PREFIX, RedisKeyConstants.SERIAL10);

        Rdrecord10DO rdrecord10 = BeanUtils.toBean(createReqVO, Rdrecord10DO.class)
                .setStatus(BpmTaskStatusEnum.SUBMIT.getStatus()).setSerialNumber(serialNumber);
        validateUserForCreateOrUpdate(rdrecord10);
        rdrecord10Mapper.insert(rdrecord10);
        // 插入子表
        createRdrecords10List(rdrecord10.getId(), createReqVO.getRdrecords10s());
        businessProcessing(createReqVO,createReqVO.getRdrecords10s());
        // 返回
        return rdrecord10.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRdrecord10(Rdrecord10SaveReqVO updateReqVO) {
        // 校验存在
        validateRdrecord10Exists(updateReqVO.getId());
        // 更新
        Rdrecord10DO updateObj = BeanUtils.toBean(updateReqVO, Rdrecord10DO.class);
        rdrecord10Mapper.updateById(updateObj);
        //获取旧数据
        List<Rdrecords10DO> oldList=rdrecords10Mapper.selectListByPid(updateReqVO.getId());
        //获取原始表单数据
        Rdrecord10DO oldRdrecord10DO=getRdrecord10(updateReqVO.getId());


        //恢复生产单数量和删除库存
        if (oldList!=null)
        {
            for(Rdrecords10DO rdrecords10DO:oldList) {
                //查询采购订单子表信息 对采购订单剩余可以入库的数量进行比对
                ProductionOrdersRespVO productionOrdersRespVO = productionOrderService.findProductionOrdersById(rdrecords10DO.getProductionOrdersId());
                    productionOrdersRespVO.setInQuantity( productionOrdersRespVO.getInQuantity() - rdrecords10DO.getQuantity());
                    productionOrderService.updateProductionOrders(productionOrdersRespVO);
                    //修改采购订单的主表数量
                    ProductionOrderDO productionOrderDO = productionOrderService.getProductionOrder(productionOrdersRespVO.getPid());
                    productionOrderDO.setProducedNumber(productionOrderDO.getProducedNumber() - rdrecords10DO.getQuantity());
                    ProductionOrderSaveReqVO productionOrderSaveReqVO = new ProductionOrderSaveReqVO();
                    BeanUtils.copyProperties(productionOrderDO, productionOrderSaveReqVO);
                    productionOrderService.updateProductionOrder(productionOrderSaveReqVO);


                //删除库存
                Rdrecords10RespVO oldRdrecords10RespVO=rdrecord10Mapper.findRdrecords10ById(rdrecords10DO.getId());
                StockDO stockDO=new StockDO().setBatchCode(rdrecords10DO.getBatch()).setInventoryId(oldRdrecords10RespVO.getInventoryId())
                        .setWarehouseId(oldRdrecord10DO.getWarehouseId()).setLocationId(oldRdrecords10RespVO.getLocationId());
                stockService.restore(stockDO);
            }
        }

        if (updateReqVO.getRdrecords10s()!=null){
            // 更新子表
            updateRdrecords10List(updateReqVO.getId(), updateReqVO.getRdrecords10s());
        }

        //重新入库
        businessProcessing(updateReqVO,updateReqVO.getRdrecords10s());





    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRdrecord10(Integer id) {
        // 校验存在
        validateRdrecord10Exists(id);

        List<Rdrecords10DO> oldList=rdrecords10Mapper.selectListByPid(id);


        //获取原始表单数据
        Rdrecord10DO oldRdrecord10DO=getRdrecord10(id);
        //恢复生产单数量 删除库存
        if (oldList!=null)
        {
            for(Rdrecords10DO rdrecords10DO:oldList) {
                //查询采购订单子表信息 对采购订单剩余可以入库的数量进行比对
                ProductionOrdersRespVO productionOrdersRespVO = productionOrderService.findProductionOrdersById(rdrecords10DO.getProductionOrdersId());
                productionOrdersRespVO.setInQuantity( productionOrdersRespVO.getInQuantity() - rdrecords10DO.getQuantity());
                productionOrderService.updateProductionOrders(productionOrdersRespVO);
                //修改采购订单的主表数量
                ProductionOrderDO productionOrderDO = productionOrderService.getProductionOrder(productionOrdersRespVO.getPid());
                productionOrderDO.setProducedNumber(productionOrderDO.getProducedNumber() - rdrecords10DO.getQuantity());
                ProductionOrderSaveReqVO productionOrderSaveReqVO = new ProductionOrderSaveReqVO();
                BeanUtils.copyProperties(productionOrderDO, productionOrderSaveReqVO);
                productionOrderService.updateProductionOrder(productionOrderSaveReqVO);

                //删除库存
                Rdrecords10RespVO oldRdrecords10RespVO=rdrecord10Mapper.findRdrecords10ById(rdrecords10DO.getId());
                StockDO stockDO=new StockDO().setBatchCode(rdrecords10DO.getBatch()).setInventoryId(oldRdrecords10RespVO.getInventoryId())
                        .setWarehouseId(oldRdrecord10DO.getWarehouseId()).setLocationId(oldRdrecords10RespVO.getLocationId());
                stockService.restore(stockDO);
            }
        }
        // 删除
        rdrecord10Mapper.deleteById(id);
        // 删除子表
        deleteRdrecords10ByPid(id);
    }

    private void validateRdrecord10Exists(Integer id) {
        if (rdrecord10Mapper.selectById(id) == null) {
            throw exception(RDRECORD10_NOT_EXISTS);
        }
    }

    @Override
    public Rdrecord10DO getRdrecord10(Integer id) {
        return rdrecord10Mapper.selectById(id);
    }

    @Override
    public PageResult<Rdrecord10DO> getRdrecord10Page(Rdrecord10PageReqVO pageReqVO) {
        return rdrecord10Mapper.selectPage(pageReqVO);
    }

    // ==================== 子表（生产入库子） ====================

    @Override
    public List<Rdrecords10DO> getRdrecords10ListByPid(Integer pid) {
        return rdrecords10Mapper.selectListByPid(pid);
    }

    @Override
    public void updateRdrecord10Status(Rdrecord10SaveReqVO reqVO) {
        rdrecord10Mapper.updateRdrecord10Status(reqVO);
    }

    @Override
    public Rdrecord10DO findByProcessInstanceId(String processInstanceId) {
        return rdrecord10Mapper.findByProcessInstanceId(processInstanceId);
    }

    public void businessProcessing(Rdrecord10SaveReqVO rdrecord10DO, List<Rdrecords10DO> rdrecords10DOList) {
        //生产入库
        for(Rdrecords10DO rdrecords10DO:rdrecords10DOList)
        {
            //查询采购订单子表信息 对采购订单剩余可以入库的数量进行比对
            ProductionOrdersRespVO productionOrdersRespVO=productionOrderService.findProductionOrdersById(rdrecords10DO.getProductionOrdersId());
            if ((productionOrdersRespVO.getQuantity()-productionOrdersRespVO.getInQuantity())>=rdrecords10DO.getQuantity())
            {
                productionOrdersRespVO.setInQuantity(productionOrdersRespVO.getInQuantity()+rdrecords10DO.getQuantity());
                productionOrderService.updateProductionOrders(productionOrdersRespVO);
                //修改采购订单的主表数量
                ProductionOrderDO productionOrderDO=productionOrderService.getProductionOrder(productionOrdersRespVO.getPid());
                productionOrderDO.setProducedNumber(productionOrderDO.getProducedNumber()+rdrecords10DO.getQuantity());
                ProductionOrderSaveReqVO productionOrderSaveReqVO=new ProductionOrderSaveReqVO();
                BeanUtils.copyProperties(productionOrderDO,productionOrderSaveReqVO);
                productionOrderService.updateProductionOrder(productionOrderSaveReqVO);
            }else {
                throw exception(RDRECORD01_NUMBER_OUT);
            }

            //执行入库方法
            StockDO stockDO=new StockDO().setQty(rdrecords10DO.getQuantity()).setInventoryId(productionOrdersRespVO.getInventoryId())
                    .setWarehouseId(rdrecord10DO.getWarehouseId()).setLocationId(rdrecords10DO.getLocationId()).setBatchCode(rdrecords10DO.getBatch());
            stockService.store(stockDO);

        }
    }

    @Override
    public List<Rdrecords10RespVO> findRdrecords10ByPid(Integer pid) {
        return rdrecord10Mapper.findRdrecords10ByPid(pid);
    }

    @Override
    public void process(Integer id) {
        /***
         * 启动流程
         */

        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = processInstanceApi.createProcessInstance(SecurityFrameworkUtils.getLoginUserId(),
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(id)));

        // 将工作流的编号，更新到 业务表单中
        rdrecord10Mapper.updateById(new Rdrecord10DO().setId(id).setProcessInstanceId(processInstanceId).setStatus(BpmTaskStatusEnum.RUNNING.getStatus()));

    }


    private void createRdrecords10List(Integer pid, List<Rdrecords10DO> list) {
        list.forEach(o -> o.setPid(pid).setBatch(batchService.generateBatch(Long.valueOf(productionOrderService.findProductionOrdersById(o.getProductionOrdersId()).getInventoryId()))));
        rdrecords10Mapper.insertBatch(list);
    }

    private void updateRdrecords10List(Integer pid, List<Rdrecords10DO> list) {
        deleteRdrecords10ByPid(pid);
		list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下：1）id 冲突；2）updateTime 不更新
        createRdrecords10List(pid, list);
    }

    private void deleteRdrecords10ByPid(Integer pid) {
        rdrecords10Mapper.deleteByPid(pid);
    }
    /***
     * 数据校验
     */
    public void validateUserForCreateOrUpdate(Rdrecord10DO rdrecord10DO)
    {
        if (rdrecord10Mapper.findCountByCode(rdrecord10DO.getSerialNumber())>0)
        {
            throw exception(RDRECORD10_SERIALNUMBER_EXISTS);
        }
    }


}